package org.hujunfeng.http;

import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @Author 胡俊丰
 * @Date 2024/7/23
 **/
public class HTTPServer {

    /**
     * 定义线程池
     */
    private static ExecutorService executorService = null;

    /**
     * 根目录，是服务器的根目录
     */
    private String rootPath = System.getProperty("user.dir") + "/../";


    /**
     * 配置文件的目录
     */
    private String configPath = rootPath + "/conf/server.txt";

    /**
     * 配置对象
     */
    private Config config = null;

    /**
     * 监听关闭的原子变量
     */
    private AtomicBoolean closeBoolean = new AtomicBoolean(false);

    /**
     * 默认的工作端口
     */
    private int port = 8080;

    /**
     * 定义TCP服务器连接套接字
     */
    private ServerSocket serverSocket;


    /**
     * 无参构造方法
     */
    public HTTPServer(){
        // 1、创建配置对象
        config = new Config();

        // 2、加载配置文件
        config.loadConfig(configPath, "UTF-8");

        // 3、设置端口
        setPort(config.getServerPort());

        // 4、初始化线程池
        executorService = createThreadPool(config);
    }

    /**
     * 创建自定义的线程池
     * @param config
     * @return
     */
    private ExecutorService createThreadPool(Config config){
            // 核心线程数
            int coreThreads = config.getCoreThreads();

            // 最大的线程数
            int maxThreads = config.getMaxThreads();

            // 阻塞队列
            BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<Runnable>(config.getMaxTasks());

            // 空闲线程休眠时间
            long freeTimeout = config.getFreeTimeout();

            // 初始化线程池
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                    coreThreads, maxThreads, freeTimeout, TimeUnit.SECONDS, blockingQueue);

            return threadPoolExecutor;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        if(port > 0 && port < 65535){
            this.port = port;
        }
    }

    public String getRootPath() {
        return rootPath;
    }


    /**
     * 用于启动服务器，监听请求，做出响应
     */
    public void start(){

        try {
            // 1、初始化服务套接字，设置端口、最大连接数、绑定的地址
            serverSocket = new ServerSocket(port, config.getMaxConnection(), InetAddress.getByName(config.getHost()));

            Logger.log("--------------------------- normally startup. ------------------------");
            Logger.log("----------------  host is: [" + config.getHost() + "]");
            Logger.log("----------------  port is: [" + getPort() + "]");

            System.out.println("----- http server work normally ------");
            System.out.println("----- host is: [" + config.getHost() + "]              ------");
            System.out.println("----- port is: [" + getPort() + "]                     ------");
            System.out.println("----- please use \"http://" + config.getHost() + ":" + getPort() + "\" to show. ------");
            

            Socket socket = null;

            // 2、定义关闭监听器
            CloseListener listener = new CloseListener(serverSocket, config, closeBoolean);

            // 3、创建线程
            Thread closeThread = new Thread(listener);

            // 4、开启线程
            closeThread.start();

            // 5、循环监听客户端连接
            while (!closeBoolean.get()) {

                // 5.1、接受客户端的连接
                socket = serverSocket.accept();

                // 5.2、生成一个Handler对象
                Handler handler = new Handler(socket, config.getReadTimeout());

                // 5.3、提交给线程池中运行
                executorService.execute(handler);
            }
        } catch (UnknownHostException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭服务端套接字
            try {
                if (serverSocket != null){
                    serverSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 关闭线程池
            executorService.shutdown();

            Logger.log("close http server.");
            Logger.close();
        }
    }

    /**
     *
     * @param args
     */
    public static void main(String[] args) {
        // 1、建立服务器对象
        HTTPServer server = new HTTPServer();

        // 2、开始运行
        server.start();
    }
}
